package main.Link;

import main.FactageApp;
import main.MainApp;
import main.SQL.MsSQLConnect;
import main.SQL.SQLRsrc;
import main.SQL.SQLTaskRsrc;
import main.Trees.ProjectNode;
import main.Trees.SmetNode;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

public class LinkTableFrame extends Thread {

    private JCheckBox copyFactsCheckBox;
    private JCheckBox copySmrFactsCheckBox;
    private JTable linkViewTable;
    private LTETableModel tableModel;
    private JButton addButton;

    private ArrayList<SmetNode> smet;
    private ArrayList<ProjectNode> work;
    private HashMap<String, SQLRsrc> rsrcs;
    private ProjectNode curProject;
    private LinkArray linkArray;
    private Connection connSql;
    public ArrayList arrCheck;
    private HashMap<String, Color> colorRow;
    private ArrayList<SQLLink> linksXLS;
    private ArrayList<SQLLink> linkBatch = null;
    private JDialog LinkTableDialog = new JDialog();

    public LinkTableFrame(LinkArray linkArray, LTETableModel tableModel, ArrayList<SmetNode> smet, ArrayList<ProjectNode> work, HashMap<String, SQLRsrc> rsrcs, ProjectNode curProject) {
        this.curProject = curProject;
        this.tableModel = tableModel;
        this.smet = smet;
        this.work = work;
        this.linkArray = linkArray;
        this.rsrcs = rsrcs;
        LinkTableDialog.setModal(true);
        this.tableModel.setParentFrame(LinkTableDialog);
    }

    public LinkTableFrame(ArrayList<SQLLink> linksXLS, ProjectNode curProject, ArrayList<ProjectNode> work, HashMap<String, SQLRsrc> rsrcs) {
        this.linksXLS = linksXLS;
        this.curProject = curProject;
        this.work = work;
        this.rsrcs = rsrcs;
    }

    public ArrayList<SQLLink> getLinks() {
        return tableModel.getData();
    }

    //region initLinkViewTable() - Форматирование таблицы связей
    private void initLinkViewTable() {

        //region Настройки отображения сетки и размеров таблицы
        linkViewTable.setShowGrid(false);
        linkViewTable.setShowHorizontalLines(true);
        linkViewTable.setRowHeight(30);

        if (linkViewTable.getColumnModel().getColumnCount() > 0) {
            linkViewTable.getColumnModel().getColumn(0).setMinWidth(10);
            linkViewTable.getColumnModel().getColumn(0).setPreferredWidth(25);
            linkViewTable.getColumnModel().getColumn(0).setMaxWidth(40);
            linkViewTable.getColumnModel().getColumn(1).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(1).setPreferredWidth(50);
            linkViewTable.getColumnModel().getColumn(1).setMaxWidth(70);
            linkViewTable.getColumnModel().getColumn(2).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(2).setPreferredWidth(50);
            linkViewTable.getColumnModel().getColumn(2).setMaxWidth(80);
            linkViewTable.getColumnModel().getColumn(4).setMinWidth(10);
            linkViewTable.getColumnModel().getColumn(4).setPreferredWidth(20);
            linkViewTable.getColumnModel().getColumn(4).setMaxWidth(50);
            linkViewTable.getColumnModel().getColumn(6).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(6).setPreferredWidth(60);
            linkViewTable.getColumnModel().getColumn(6).setMaxWidth(80);
            linkViewTable.getColumnModel().getColumn(7).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(7).setPreferredWidth(50);
            linkViewTable.getColumnModel().getColumn(7).setMaxWidth(60);
            linkViewTable.getColumnModel().getColumn(8).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(8).setPreferredWidth(60);
            linkViewTable.getColumnModel().getColumn(8).setMaxWidth(80);
            linkViewTable.getColumnModel().getColumn(9).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(9).setPreferredWidth(60);
            linkViewTable.getColumnModel().getColumn(9).setMaxWidth(80);
            linkViewTable.getColumnModel().getColumn(10).setMinWidth(10);
            linkViewTable.getColumnModel().getColumn(10).setPreferredWidth(25);
            linkViewTable.getColumnModel().getColumn(10).setMaxWidth(30);
            linkViewTable.getColumnModel().getColumn(11).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(11).setPreferredWidth(40);
            linkViewTable.getColumnModel().getColumn(11).setMaxWidth(60);
            linkViewTable.getColumnModel().getColumn(12).setMinWidth(20);
            linkViewTable.getColumnModel().getColumn(12).setPreferredWidth(60);
            linkViewTable.getColumnModel().getColumn(12).setMaxWidth(120);
        }
        //endregion

        arrCheck = new ArrayList();
        for (int i = 1; i < 13; i++) {
            linkViewTable.getColumnModel().getColumn(i).setCellRenderer(new ColorTableCellRenderer(arrCheck, colorRow));
        }

        linkViewTable.getColumnModel().getColumn(3).setCellRenderer(new CellRenderer(arrCheck, colorRow));
        linkViewTable.getColumnModel().getColumn(5).setCellRenderer(new CellRenderer(arrCheck, colorRow));
        linkViewTable.getColumnModel().getColumn(0).setCellRenderer(new ColorCheckBoxRenderer(arrCheck, colorRow));
        linkViewTable.getColumnModel().getColumn(10).setCellRenderer(new ColorCheckBoxRenderer(arrCheck, colorRow));

        DefaultCellEditor singleclick = (DefaultCellEditor) linkViewTable.getDefaultEditor(Double.class);
        singleclick.setClickCountToStart(1);

        linkViewTable.setDefaultEditor(linkViewTable.getColumnClass(8), singleclick);
        linkViewTable.setDefaultEditor(linkViewTable.getColumnClass(9), singleclick);
//        linkViewTable.setBorder(new CompoundBorder(new EmptyBorder(new Insets(10,10,10,10)), linkViewTable.getBorder()));

        TableCellEditor tableCellEditor = linkViewTable.getDefaultEditor(Double.class);
        tableCellEditor.addCellEditorListener(new CellEditorListener() {
            @Override
            public void editingStopped(ChangeEvent changeEvent) {
                if (linkViewTable.getSelectedColumn() != 11 ) {

                    if (linkViewTable.getSelectedColumn() == 8 && copyFactsCheckBox.isSelected())
                        copyFacts(linkViewTable.getSelectedRow());

                    if (linkViewTable.getSelectedColumn() == 8 && copySmrFactsCheckBox.isSelected())
                        copySmrFacts(linkViewTable.getSelectedRow());

                    if (linkViewTable.getSelectedColumn() == 9) {
                        setFullFactor(linkViewTable.getSelectedRow());
                    }


                    checkFactor(linkViewTable.getSelectedRow());
                }
                linkViewTable.validate();
            }

            @Override
            public void editingCanceled(ChangeEvent changeEvent) {
                System.out.println("Canceled");
            }
        });
    }
    //endregion

    //region openLinkTable() - Инициализация компонентов формы
    public void run() {

        initData();

        //Массив цветов для сметных строк
        ArrayList<Color> colorArrayList = new ArrayList<>();
        colorArrayList.add(0, new Color(236, 255, 217));
        colorArrayList.add(1, new Color(217, 255, 255));
        colorArrayList.add(2, new Color(221, 217, 255));
        colorArrayList.add(3, new Color(217, 244, 255));
        colorArrayList.add(4, new Color(255, 255, 217));
        colorArrayList.add(5, new Color(228, 217, 255));

        //region Старые мрачные цвета
//        colorArrayList.add(0, new Color(220, 225, 215));
//        colorArrayList.add(1, new Color(214, 225, 225));
//        colorArrayList.add(2, new Color(217, 216, 225));
//        colorArrayList.add(3, new Color(215, 222, 225));
//        colorArrayList.add(4, new Color(225, 225, 211));
//        colorArrayList.add(5, new Color(220, 218, 225));
        //endregion


        colorRow = new HashMap<>();

        String smr_id_ideal = tableModel.getData().get(0).getSmrNum();
        colorRow.put(smr_id_ideal, colorArrayList.get(0));
        int j = 0;

        for (int i = 1; i < tableModel.getRowCount(); i++) {
            if (!tableModel.getData().get(i).getSmrNum().equals(smr_id_ideal)) {
                smr_id_ideal = tableModel.getData().get(i).getSmrNum();
                if (j < 5) {
                    j++;
                } else {
                    j = 0;
                }
                colorRow.put(smr_id_ideal, colorArrayList.get(j));
            }
        }

        JPanel panel = new JPanel();
        panel.setBackground(new Color(255, 255, 255));
        int width = 1000;
        int height = 750;
        LinkTableDialog.setSize(new Dimension(width, height));
        Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
        LinkTableDialog.setLocation(screensize.width / 2 - width / 2, screensize.height / 2 - height / 2);

        //Менеджер компоновки и раскладка элменетов на UI. Начало.

        GridBagConstraints c;
        panel.setLayout(new GridBagLayout());

        JLabel header = new JLabel("Следующие связи будут добавлены или изменены");
        header.setFont(new Font("Segoe UI Light", 0, 18));

        c = new GridBagConstraints();
        c.gridx = 1;
        c.gridy = 0;
        c.gridwidth = 4;
        c.insets = new Insets(25, 25, 5, 0);
        c.anchor = GridBagConstraints.WEST;
        panel.add(header, c);

        JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
        separator.setForeground(SystemColor.activeCaptionBorder);
        c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 5;
        c.insets = new Insets(5, 0, 10, 0);
        c.fill = GridBagConstraints.HORIZONTAL;
        panel.add(separator, c);

        copyFactsCheckBox = new JCheckBox("Копировать коэффициенты по работам");
        copyFactsCheckBox.setBackground(SystemColor.window);
        c = new GridBagConstraints();
        c.gridx = 3;
        c.gridy = 2;
        c.insets = new Insets(0, 25, 5, 50);
        c.anchor = GridBagConstraints.EAST;
        panel.add(copyFactsCheckBox, c);

        //region Копирование всех коэффициентов
        copySmrFactsCheckBox = new JCheckBox("Копировать коэффициенты по сметам");
        copySmrFactsCheckBox.setBackground(SystemColor.window);
        c = new GridBagConstraints();
        c.gridx = 3;
        c.gridy = 3;
        c.insets = new Insets(0, 25, 5, 50);
        c.anchor = GridBagConstraints.WEST;
        //panel.add(copySmrFactsCheckBox, c);
        //endregion


        //region Для редакции Фактаж ТХМ
        JButton invertPv = new JButton("Изменить все флаги ФО");
        invertPv.setBackground(SystemColor.window);
        c = new GridBagConstraints();
        c.gridx = 3;
        c.gridy = 3;
        c.insets = new Insets(0, 25, 5, 120);
        c.anchor = GridBagConstraints.EAST;
        invertPv.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                invertAllPv();
            }
        });
        panel.add(invertPv, c);
        //endregion

        //region Для редакции Фактаж ТХМ
        JButton thmButton = new JButton("Коэффициенты для ТХМ");
        thmButton.setBackground(SystemColor.window);
        c = new GridBagConstraints();
        c.gridx = 3;
        c.gridy = 4;
        c.insets = new Insets(0, 25, 5, 120);
        c.anchor = GridBagConstraints.EAST;
        thmButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                calcThm();
            }
        });
        panel.add(thmButton, c);
        //endregion


        linkViewTable = new JTable(tableModel);
        JScrollPane jScrollPane = new JScrollPane(linkViewTable);
        jScrollPane.setPreferredSize(new Dimension(450, 250));
        c = new GridBagConstraints();
        c.gridx = 1;
        c.gridy = 5;
        c.gridwidth = 3;
        c.weightx = 1;
        c.weighty = 1;
        c.insets = new Insets(0, 25, 10, 25);
        c.fill = GridBagConstraints.BOTH;
        panel.add(jScrollPane, c);
        initLinkViewTable();

        addButton = new JButton("Добавить");
        c = new GridBagConstraints();
        c.gridx = 2;
        c.gridy = 6;
        c.gridwidth = 1;
        c.insets = new Insets(0, 25, 30, 5);
        c.anchor = GridBagConstraints.WEST;
        c.weightx = 0;
        c.weighty = 0;
        panel.add(addButton, c);

        JButton cancelButton = new JButton("Отмена");
        c = new GridBagConstraints();
        c.gridx = 3;
        c.gridy = 6;
        c.insets = new Insets(0, 0, 30, 25);
        c.anchor = GridBagConstraints.WEST;
        panel.add(cancelButton, c);

        //Менеджер компоновки и раскладки элементов. Конец.

        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
            try {
                LinkTableDialog.setVisible(false);
                connSql = MsSQLConnect.ConnectDB("Factage");
                for (SQLLink link : getLinks()) {
                    addLinks(link);
                }
                long start;
                long finish;

                start = System.currentTimeMillis();
                getLinksSum();
                finish = System.currentTimeMillis() - start;
                System.out.println("getLinksSum(): " + finish);

                start = System.currentTimeMillis();
                updateLinks();
                finish = System.currentTimeMillis() - start;
                System.out.println("updateLinks(): " + finish);

                start = System.currentTimeMillis();
                updateTasks();
                finish = System.currentTimeMillis() - start;
                System.out.println("updateTasks(): " + finish);

                start = System.currentTimeMillis();
                connSql.close();
                finish = System.currentTimeMillis() - start;
                System.out.println("connSql.close(): " + finish);

                FactageApp.ma.getDataAddLink();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            }
        });

        copyFactsCheckBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {

            }
        });

        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                LinkTableDialog.setVisible(false);
            }
        });

        LinkTableDialog.add(panel);
        LinkTableDialog.setVisible(true);
    }
    //endregion

    //region initData() - формирование таблицы добавления связей
    private void initData() {
        BigDecimal editWork = new BigDecimal(0);

        for (SmetNode smr : smet) {
            int countEdit = 0;

            for (ProjectNode workEdit : work) {
                for (SQLLink curLink : linkArray.getLinkArray()) {
                    if (curLink.getTaskId() == workEdit.getId() && curLink.getSmrId() == smr.getId()) {
                        countEdit++;
                        break;
                    }
                }
            }

            BigDecimal factCheck = new BigDecimal(0);

            for (ProjectNode wrk : work) {
                String act = "Создать";
                SQLLink oldLink = new SQLLink();
                for (SQLLink curLink : linkArray.getLinkArray()) {
                    if (curLink.getTaskId() == wrk.getId() && curLink.getSmrId() == smr.getId()) {
                        oldLink = curLink;
                        act = "Изменить";
                        break;
                    }
                }
                SQLLink lnk;
                if (act.equals("Изменить")) {
                    lnk = new SQLLink(oldLink.getId(), act, wrk.getShortName(), wrk.getName(), smr.getNum(), smr.getName(), smr.getVolume(), oldLink.getFact(), smr.getFactorFull(), oldLink.getPv(), wrk.getId(), smr.getId(), oldLink.getSmNum(), oldLink.getPvVol(), smr.getUnit());
                    lnk.setIsImportFactage(smr.getIsImportFactage());
                    lnk.setPvType(wrk.getTaskCodeValue());

                    BigDecimal pvVol = smr.getVolume().multiply(oldLink.getFact()).divide(smr.getFactorFull(), 6, RoundingMode.HALF_UP);
//                    factCheck = factCheck.add(smr.getFactor());

                    if (!oldLink.getPv()) {
                        lnk.applyUnitMultiplier(pvVol);
                    } else {
                        lnk.calcUnit(pvVol);
                    }

                } else {
                    factCheck = factCheck.add(smr.getFactorFull().subtract(smr.getFactor()).divide(new BigDecimal(work.size() - countEdit), 6, BigDecimal.ROUND_HALF_UP));
                    BigDecimal factPlease = new BigDecimal(0.000000);
                    if (smr.getFactorFull().subtract(factCheck).subtract(smr.getFactor()).compareTo(new BigDecimal(0.00001)) > 0 || smr.getFactorFull().subtract(factCheck).subtract(smr.getFactor()).multiply(new BigDecimal(-1)).compareTo(new BigDecimal(0.00001)) > 0) {
                        factPlease = smr.getFactorFull().subtract(smr.getFactor()).divide(new BigDecimal(work.size() - countEdit), 6, BigDecimal.ROUND_HALF_UP);
                    } else {
                        factPlease = smr.getFactorFull().subtract(factCheck).subtract(smr.getFactor()).add(smr.getFactorFull().subtract(smr.getFactor()).divide(new BigDecimal(work.size() - countEdit), 6, BigDecimal.ROUND_HALF_UP));
                    }
                    BigDecimal pvVol = smr.getVolume().multiply(factPlease).divide(smr.getFactorFull(), 6, RoundingMode.HALF_UP);

                    lnk = new SQLLink(oldLink.getId(), act, wrk.getShortName(), wrk.getName(), smr.getNum(), smr.getName(), smr.getVolume(), factPlease, smr.getFactorFull(), false, wrk.getId(), smr.getId(), smr.getSmNum(), pvVol, smr.getUnit());
                    lnk.setIsImportFactage(smr.getIsImportFactage());
                    lnk.setPvType(wrk.getTaskCodeValue());
                    lnk.applyUnitMultiplier(pvVol);
                }
                tableModel.getData().add(lnk);
            }
        }
    }
    //endregion

    //region Добавление связей из Excel
    //region addExcelLinks() - метод добавления связей из файла Excel
    public void addExcelLinks() {

        try {
            connSql = MsSQLConnect.ConnectDB("Factage");

            for (SQLLink link : linksXLS) {
                addOneExcelLink(link);
            }

            connSql.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //endregion

    //region addOneExcelLink(SQLLink link) - метод добавления связи по одной, вызывается из addExcelLinks()
    private void addOneExcelLink(SQLLink link) {

        for (ProjectNode task : work) {
            if (link.getTaskId() != task.getId()) continue;

            if (link.getPv() && !task.getTaskCodeValue().equals("")) {
                checkRsrc(task, task.getTaskCodeValue(), link.getPvVol().doubleValue());
            }
            checkRsrc(task, "MECH", link.getMechVol().doubleValue());
            checkRsrc(task, "T", link.getTVol().doubleValue());
            checkRsrc(task, "MR", link.getMrVol().doubleValue());
        }

        link.updateSQL(connSql);
    }
    //endregion
    //endregion

    //region addLinks(SQLLink link) - Добавление связей из формы
    private void addLinks(SQLLink newLink) {
        if (!newLink.getPv()) newLink.setPvVol(new BigDecimal(0));
        if (newLink.getFact().signum() == 0 || !newLink.getAsk()) return;

        //region Поиск и удаление старой связи
        if (newLink.getAction().equals("Изменить")) {

            SQLLink oldLink = MainApp.linkSmrMap.get(newLink.getSmrMapId()).get(newLink.getTaskId());
            if (linkArray.getLinkArray().contains(oldLink)) linkArray.getLinkArray().remove(oldLink);

            MainApp.linkSmrMap.get(newLink.getSmrMapId()).remove(newLink.getTaskId());
            MainApp.taskMap.get(newLink.getTaskId()).getLinks().remove(newLink.getSmrMapId());
        }
        //endregion

        for (SmetNode smr : smet) {
            if (newLink.getSmrId() != smr.getId()) continue;

            BigDecimal multiplier = newLink.getFact().divide(newLink.getFactFull(), 6, RoundingMode.HALF_UP);

            //region Назначение объемов ресурсов связи
            newLink.setMechVol(smr.getMR().multiply(multiplier).setScale(6, RoundingMode.HALF_UP));
            newLink.setTVol(smr.getHR().multiply(multiplier).setScale(6, RoundingMode.HALF_UP));
            newLink.setMrVol(smr.getCost().multiply(multiplier).setScale(6, RoundingMode.HALF_UP));
            //endregion
        }

    }
    //endregion

    //region updateLinks() - Обновление связей в SQL, вызывается из addLinks()
    private void updateLinks () throws SQLException {

        CallableStatement stmt, stmtUpdate, stmtInsert;
        ResultSet rs;
        HashMap<String, Integer> hashBatch = new HashMap<>();

        stmt = connSql.prepareCall("{call getLinksBatch(?, ?)}");
        stmt.setString(1, curProject.getDbName());
        stmt.setInt(2, curProject.getId());

        rs = stmt.executeQuery();
        while (rs.next()) {
            hashBatch.put(rs.getString("task_id") + "_" + rs.getString("smr_id"), rs.getInt("link_id"));
        }

        stmtUpdate = connSql.prepareCall("{call updateLinkBatch(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
        stmtInsert = connSql.prepareCall("{call insertLinkBath(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");

        int i = 0;
        for (SQLLink lnk : (linkBatch == null ? getLinks() :linkBatch)) {
            if (lnk.getFact().signum() == 0 || !lnk.getAsk()) continue;
            if (hashBatch.containsKey(String.valueOf(lnk.getTaskId()) + "_" + String.valueOf(lnk.getSmrId()))) {
                stmtUpdate.setString(1, curProject.getDbName());
                stmtUpdate.setInt(2, curProject.getId());
                stmtUpdate.setInt(3, lnk.getTaskId());
                stmtUpdate.setInt(4, lnk.getSmrId());
                stmtUpdate.setString(5, lnk.getSmrName());
                stmtUpdate.setString(6, lnk.getSmrNum());
                stmtUpdate.setString(7, lnk.getSmNum());
                stmtUpdate.setFloat(8, lnk.getSmrVol().floatValue());
                stmtUpdate.setFloat(9, lnk.getFact().floatValue());
                stmtUpdate.setFloat(10, lnk.getFactFull().floatValue());
                stmtUpdate.setFloat(11, lnk.getPv() ? lnk.getPvVol().floatValue() : (float) 0.0);
                stmtUpdate.setFloat(12, lnk.getMechVol().floatValue());
                stmtUpdate.setFloat(13, lnk.getTVol().floatValue());
                stmtUpdate.setFloat(14, lnk.getMrVol().floatValue());
                stmtUpdate.setString(15, lnk.getPv().toString());
                stmtUpdate.setString(16, lnk.getIsImportFactage() ? "true" : "");
                stmtUpdate.setString(17, lnk.getSmrUnit());
                stmtUpdate.setInt(18, hashBatch.get(lnk.getTaskId() + "_" + lnk.getSmrId()));
                stmtUpdate.addBatch();
            } else {
                stmtInsert.setString(1, curProject.getDbName());
                stmtInsert.setInt(2, curProject.getId());
                stmtInsert.setInt(3, lnk.getTaskId());
                stmtInsert.setInt(4, lnk.getSmrId());
                stmtInsert.setString(5, lnk.getSmrName());
                stmtInsert.setString(6, lnk.getSmrNum());
                stmtInsert.setString(7, lnk.getSmNum());
                stmtInsert.setFloat(8, lnk.getSmrVol().floatValue());
                stmtInsert.setFloat(9, lnk.getFact().floatValue());
                stmtInsert.setFloat(10, lnk.getFactFull().floatValue());
                stmtInsert.setFloat(11, lnk.getPv() ? lnk.getPvVol().floatValue() : (float) 0.0);
                stmtInsert.setFloat(12, lnk.getMechVol().floatValue());
                stmtInsert.setFloat(13, lnk.getTVol().floatValue());
                stmtInsert.setFloat(14, lnk.getMrVol().floatValue());
                stmtInsert.setString(15, lnk.getPv().toString());
                stmtInsert.setString(16, lnk.getIsImportFactage() ? "true" : "");
                stmtInsert.setString(17, lnk.getSmrUnit());
                stmtInsert.addBatch();
            }
        }

//        stmt = connSql.prepareCall("{call updateBatchLinkImportFactage1(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}");
//
//        for (SQLLink lnk : (linkBatch == null ? getLinks() :linkBatch)) {
//
//            if (lnk.getFact().signum() == 0 || !lnk.getAsk()) continue;
//
//            stmt.setString(1, curProject.getDbName());
//            stmt.setInt(2, curProject.getId());
//            stmt.setInt(3, lnk.getTaskId());
//            stmt.setInt(4, lnk.getSmrId());
//            stmt.setString(5, lnk.getSmrName());
//            stmt.setString(6, lnk.getSmrNum());
//            stmt.setString(7, lnk.getSmNum());
//            stmt.setFloat(8, lnk.getSmrVol().floatValue());
//            stmt.setFloat(9, lnk.getFact().floatValue());
//            stmt.setFloat(10, lnk.getFactFull().floatValue());
//            stmt.setFloat(11, lnk.getPv() ? lnk.getPvVol().floatValue() : (float) 0.0);
//            stmt.setFloat(12, lnk.getMechVol().floatValue());
//            stmt.setFloat(13, lnk.getTVol().floatValue());
//            stmt.setFloat(14, lnk.getMrVol().floatValue());
//            stmt.setString(15, lnk.getPv().toString());
//            stmt.setString(16, lnk.getIsImportFactage() ? "true" : "");
//            stmt.setString(17, lnk.getSmrUnit());
//            stmt.addBatch();
//        }

//        long timeStart = System.currentTimeMillis();
//        stmt.executeBatch();
//        long time = System.currentTimeMillis() - timeStart;
//        System.out.println("executeBatch: " + time);
        stmt.close();

        stmtInsert.executeBatch();
        stmtInsert.close();

        stmtUpdate.executeBatch();
        stmtUpdate.close();

    }
    //endregion

    //region getLinksSum () - Внесение назначений в работы и сметы по сумме из связей, вызывается по кнопке
    private void getLinksSum() {

        for (ProjectNode task : work) {

            BigDecimal trPv, trMech, trMr, trT;
            trPv = new BigDecimal(0);
            trMech = new BigDecimal(0);
            trMr = new BigDecimal(0);
            trT = new BigDecimal(0);

            for (SQLLink lnk : getLinks()) {
                if (lnk.getTaskId() != task.getId()) continue;
                trPv = trPv.add(lnk.getPvVol() != null ? lnk.getPvVol() : new BigDecimal(0));
                trMech = trMech.add(lnk.getMechVol() != null ? lnk.getMechVol() : new BigDecimal(0));
                trMr = trMr.add(lnk.getMrVol() != null ? lnk.getMrVol() : new BigDecimal(0));
                trT = trT.add(lnk.getTVol() != null ? lnk.getTVol() : new BigDecimal(0));
            }

            for (SQLLink lnk : task.getLinks().values()) {
                if (lnk.getTaskId() != task.getId()) continue;
                trPv = trPv.add(lnk.getPvVol());
                trMech = trMech.add(lnk.getMechVol());
                trMr = trMr.add(lnk.getMrVol());
                trT = trT.add(lnk.getTVol());
            }

            task.getRsrc().clear();
            if (trPv.compareTo(new BigDecimal(0.001)) == 1) {
                SQLRsrc rsr = rsrcs.get(task.getTaskCodeValue());
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\""+task.getTaskCodeValue()+"\" не был найден.\nНазначение не выполнено.\n\n", "Назначение не выполнено", JOptionPane.ERROR_MESSAGE);
                } else {

                    SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trPv.doubleValue(), "", curProject.getDbName(), curProject.getId());
                    task.getRsrc().add(tr);
                    task.setTaskUse("true");
                }
            }

            if (trMech.compareTo(new BigDecimal(0.001)) == 1) {
                SQLRsrc rsr = rsrcs.get("MECH");
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\"MECH\" не был найден.\nНазначение не выполнено.\n\n", "Назначение не выполнено", JOptionPane.ERROR_MESSAGE);
                } else {
                    SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trMech.doubleValue(), "", curProject.getDbName(), curProject.getId());
                    task.getRsrc().add(tr);
                    task.setTaskUse("true");
                }
            }

            if (trT.compareTo(new BigDecimal(0.001)) == 1) {

                //region Description
                PVCode code = new PVCode();
                String rsrcShortName = code.getRsrcShortName(task.getTaskCodeValue());

                if (!rsrcShortName.equals("T") && task.getConstrCode() != null) {
                    rsrcShortName = rsrcShortName + "-" + task.getConstrCode();
                } else if (!rsrcShortName.equals("T") && curProject.getProjCode() != null) {
                    rsrcShortName = rsrcShortName + "-" + curProject.getProjCode();
                }
                //endregion

                SQLRsrc rsr = rsrcs.get(rsrcShortName);
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\"" + rsrcShortName + "\" не был найден.\n Будет назначен общий ресурс трудозатрат.\n\n", "Предупреждение", JOptionPane.INFORMATION_MESSAGE);
                    rsr = rsrcs.get("T");
               } 

                SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trT.doubleValue(), "", curProject.getDbName(), curProject.getId());
                task.getRsrc().add(tr);
                task.setTaskUse("true");

            }
            if (trMr.compareTo(new BigDecimal(0.001)) == 1) {
                SQLRsrc rsr = rsrcs.get("MR");
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\"MR\" не был найден.\nНазначение не выполнено.\n\n", "Назначение не выполнено", JOptionPane.ERROR_MESSAGE);
                } else {
                    SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trMr.doubleValue(), "", curProject.getDbName(), curProject.getId());
                    task.getRsrc().add(tr);
                    task.setTaskUse("true");
                }
            }
        }

        //region Назначение коэффициента смете и проверка распределенного физ. объема связи
        for (SmetNode smr : smet) {

            BigDecimal factSum = new BigDecimal(0);

            //region Сумма коэффициентов и распределенных ФО в добавляемых связях
            for (SQLLink lnk : getLinks()) {
                if (lnk.getSmrId() != smr.getId()) continue;
                factSum = factSum.add(lnk.getFact());
            }
            //endregion

            //region Сумма коэффициентов и распред. ФО с учетом всех связей
            if (MainApp.linkSmrMap.containsKey((smr.getIsImportFactage() ? 1 : 0) + "-" + smr.getId())) {
                for (SQLLink lnk : MainApp.linkSmrMap.get((smr.getIsImportFactage() ? 1 : 0)+"-"+smr.getId()).values()) {
                    factSum = factSum.add(lnk.getFact());
                }
            }
            //endregion

            //region Коэффициент К в дереве смет
            smr.setFactor(factSum.setScale(6, RoundingMode.HALF_UP));
            //endregion

            smr.setSmetHighlight();
        }
        //endregion
    }
    //endregion

    //region updateTasks() - Обновление назначений ресурсов в SQL, вызывается из addLinks()
    private void updateTasks () throws SQLException {

        CallableStatement stmt = connSql.prepareCall("{call prepareBatchTaskRsrc(?, ?, ?)}");
        for (ProjectNode task : work) {
            stmt.setString(1, curProject.getDbName());
            stmt.setInt(2, curProject.getId());
            stmt.setInt(3, task.getId());
            stmt.addBatch();
        }

        stmt.executeBatch();

        stmt = connSql.prepareCall("{call updateBatchTaskRsrc(?, ?, ?, ?, ?)}");
        for (ProjectNode task : work) {
            for (SQLTaskRsrc tr : task.getRsrc()) {
                stmt.setString(1, tr.getDbName());
                stmt.setInt(2, curProject.getId());
                stmt.setInt(3, task.getId());
                stmt.setInt(4, tr.getRsrcId());
                stmt.setFloat(5, (float) tr.getPlannedUnits());
                stmt.addBatch();
            }
        }
        stmt.executeBatch();

        stmt.close();
    }
    //endregion

    //region checkRsrc(ProjectNode task, String rsrShortName, Double plannedUnits) - Проверка и добавление назначений ресурсов в task, вызывается из addlink()
    private void checkRsrc(ProjectNode task, String rsrShortName, Double plannedUnits) {
        for (SQLTaskRsrc tr : task.getRsrc()) {
            if (tr.getRsrcShortName().equals(rsrShortName)) {
                Double units = tr.getPlannedUnits();
                tr.setPlannedUnits(plannedUnits + units);
                if (plannedUnits + units < 0.001) task.getRsrc().remove(tr);
                return;
            }
        }

        if (plannedUnits > 0.001) {
            SQLRsrc rsr = rsrcs.get(rsrShortName);
            if (rsr == null) {
                JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\"" + rsrShortName + "\" не был найден.\nНазначение не выполнено.\n\n", "Назначение не выполнено", JOptionPane.ERROR_MESSAGE);
            } else {
                SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), plannedUnits, "", curProject.getDbName(), curProject.getId());
                task.getRsrc().add(tr);
            }
        }
    }
    //endregion

    //region invertAllPv() - метод для простановки флагов ФО, для редакции Factage - ТХМ
    private void invertAllPv() {
        for (SQLLink link : tableModel.getData()) {
            link.setPv(!link.getPv());
        }
    }
    //endregion

    private void calcThm() {

        BigDecimal pv17Count = new BigDecimal(0);
        BigDecimal pv08Count = new BigDecimal(0);

        for (ProjectNode task : work) {
            if (task.getTaskCodeValue().equals("PV17")) {
                pv17Count = pv17Count.add(new BigDecimal(1));
            } else if (task.getTaskCodeValue().equals("PV08")) {
                pv08Count = pv08Count.add(new BigDecimal(1));
            }
        }

        for (SmetNode smr : smet) {

            BigDecimal factCheck = new BigDecimal(0);
            for (SQLLink link : tableModel.getData()) {
                if (link.getSmrId() == smr.getId()) {
                    ProjectNode task = MainApp.taskMap.get(link.getTaskId());
                    if (task.getTaskCodeValue().equals("PV17") || task.getTaskCodeValue().equals("PV08")) {

                        BigDecimal pvFact = new BigDecimal(task.getTaskCodeValue().equals("PV17") ? 0.03 : 0.97);
                        BigDecimal taskCount = task.getTaskCodeValue().equals("PV17") ? pv17Count : pv08Count;

                        factCheck = factCheck.add((pvFact).divide(taskCount, 6, BigDecimal.ROUND_HALF_UP));
                        BigDecimal factPlease = new BigDecimal(0.000000);

                        if (pvFact.subtract(factCheck).compareTo(new BigDecimal(0.00001)) > 0 || pvFact.subtract(factCheck).multiply(new BigDecimal(-1)).compareTo(new BigDecimal(0.00001)) > 0) {
                            factPlease = pvFact.divide(taskCount, 6, BigDecimal.ROUND_HALF_UP);
                        } else {
                            factPlease = pvFact.subtract(factCheck).add((pvFact).divide(taskCount, 6, BigDecimal.ROUND_HALF_UP));
                        }
                        if (task.getTaskCodeValue().equals("PV17")) {
                            BigDecimal pvVol = smr.getVolume().multiply(smr.getFactorFull()).divide(smr.getFactorFull(), 6, RoundingMode.HALF_UP);
                            link.applyUnitMultiplier(pvVol);
                        }

                        link.setFact(factPlease);
                    }
                }
            }
        }
    }

    //region copyFacts(int row) - метод для дублирования коэффициентов в форме
    private void copyFacts(int row) {
        BigDecimal factValue = new BigDecimal(tableModel.getValueAt(row, 8).toString()).setScale(6, RoundingMode.HALF_UP);

        for (SQLLink link : tableModel.getData()) {
            if (link.getTaskId() == tableModel.getTaskObjId(row)) {
                link.setFact(factValue);
            }
        }
    }
    //endregion

    //region copySmrFacts(int row) - метод для дублирования коэффициентов в форме
    private void copySmrFacts(int row) {
        //int task_id = tableModel.getTaskObjId(row);
        BigDecimal factValue = new BigDecimal(tableModel.getValueAt(row, 8).toString()).setScale(6, RoundingMode.HALF_UP);

        for (SQLLink link : tableModel.getData()) {
//            if (link.getTaskId() == task_id ) {
                link.setFact(factValue);
  //          }
        }
    }
    //endregion

    private void setFullFactor(int row) {

        SQLLink curLink = tableModel.getLink(row);

        //region Устанавливаем новый FactFull в смете и получаеем старый
        BigDecimal oldFactFull = new BigDecimal(0);
        if (MainApp.allSmrMap.containsKey(curLink.getSmrMapId())) {
            SmetNode smr = MainApp.allSmrMap.get(curLink.getSmrMapId());
            oldFactFull = smr.getFactorFull();
            smr.setFactorFull(curLink.getFactFull());

        }
        //endregion

        //region Проставляем новый FactFull в добавляемых связях по этой смете
        for (SQLLink link : tableModel.getData()) {
            if (link.getSmrId() == curLink.getSmrId()) {
                link.setFactFull(curLink.getFactFull());
                link.applyUnitMultiplier(link.getSmrVol().multiply(link.getFact()).divide(link.getFactFull(), 6, RoundingMode.HALF_UP));
            }
        }
        //endregion

        connSql = MsSQLConnect.ConnectDB("Factage");

        if (!MainApp.linkSmrMap.containsKey(curLink.getSmrMapId())) return;

        linkBatch = new ArrayList<>();
        work = new ArrayList<>();

        setSmrFF(curLink, oldFactFull);

        try {
            updateLinks();
            updateTasks();
            connSql.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        linkBatch = null;

    }

    private void setSmrFF(SQLLink curLink, BigDecimal oldFactFull) {

        for (SQLLink link : MainApp.linkSmrMap.get(curLink.getSmrMapId()).values()) {

            link.setFactFull(curLink.getFactFull());
            link.setPvVol(link.getPvVol().multiply(oldFactFull).divide(curLink.getFactFull(), 6, RoundingMode.HALF_UP));
            link.setTVol(link.getTVol().multiply(oldFactFull).divide(curLink.getFactFull(), 6, RoundingMode.HALF_UP));
            link.setMechVol(link.getMechVol().multiply(oldFactFull).divide(curLink.getFactFull(), 6, RoundingMode.HALF_UP));
            link.setMrVol(link.getMrVol().multiply(oldFactFull).divide(curLink.getFactFull(), 6, RoundingMode.HALF_UP));

            ProjectNode task = MainApp.taskMap.get(link.getTaskId());

            BigDecimal trPv, trMech, trMr, trT;
            trPv = new BigDecimal(0);
            trMech = new BigDecimal(0);
            trMr = new BigDecimal(0);
            trT = new BigDecimal(0);

            for (SQLLink lnk : getLinks()) {
                if (lnk.getTaskId() != task.getId()) continue;
                trPv = trPv.add(lnk.getPvVol() != null ? lnk.getPvVol() : new BigDecimal(0));
                trMech = trMech.add(lnk.getMechVol() != null ? lnk.getMechVol() : new BigDecimal(0));
                trMr = trMr.add(lnk.getMrVol() != null ? lnk.getMrVol() : new BigDecimal(0));
                trT = trT.add(lnk.getTVol() != null ? lnk.getTVol() : new BigDecimal(0));
            }

            for (SQLLink lnk : task.getLinks().values()) {
                if (lnk.getTaskId() != task.getId()) continue;
                trPv = trPv.add(lnk.getPvVol());
                trMech = trMech.add(lnk.getMechVol());
                trMr = trMr.add(lnk.getMrVol());
                trT = trT.add(lnk.getTVol());
            }

            task.getRsrc().clear();
            if (trPv.compareTo(new BigDecimal(0.001)) == 1) {
                SQLRsrc rsr = rsrcs.get(task.getTaskCodeValue());
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\""+task.getTaskCodeValue()+"\" не был найден.\nНазначение не выполнено.\n\n", "Назначение не выполнено", JOptionPane.ERROR_MESSAGE);
                } else {
                    SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trPv.doubleValue(), "", curProject.getDbName(), curProject.getId());
                    task.getRsrc().add(tr);
                    task.setTaskUse("true");
                }
            }

            if (trMech.compareTo(new BigDecimal(0.001)) == 1) {
                SQLRsrc rsr = rsrcs.get("MECH");
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\"MECH\" не был найден.\nНазначение не выполнено.\n\n", "Назначение не выполнено", JOptionPane.ERROR_MESSAGE);
                } else {
                    SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trMech.doubleValue(), "", curProject.getDbName(), curProject.getId());
                    task.getRsrc().add(tr);
                    task.setTaskUse("true");
                }
            }

            if (trT.compareTo(new BigDecimal(0.001)) == 1) {

                //region Description
                PVCode code = new PVCode();
                String rsrcShortName = code.getRsrcShortName(task.getTaskCodeValue());

                if (!rsrcShortName.equals("T") && curProject.getProjCode() != null) {
                    rsrcShortName = rsrcShortName + "-" + curProject.getProjCode();
                }
                //endregion

                SQLRsrc rsr = rsrcs.get(rsrcShortName);
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\"" + rsrcShortName + "\" не был найден.\n Будет назначен общий ресурс трудозатрат.\n\n", "Предупреждение", JOptionPane.INFORMATION_MESSAGE);
                    rsr = rsrcs.get("T");
                }

                SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trT.doubleValue(), "", curProject.getDbName(), curProject.getId());
                task.getRsrc().add(tr);
                task.setTaskUse("true");

            }
            if (trMr.compareTo(new BigDecimal(0.001)) == 1) {
                SQLRsrc rsr = rsrcs.get("MR");
                if (rsr == null) {
                    JOptionPane.showMessageDialog(LinkTableDialog, "Ресурс с ID:\"MR\" не был найден.\nНазначение не выполнено.\n\n", "Назначение не выполнено", JOptionPane.ERROR_MESSAGE);
                } else {
                    SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trMr.doubleValue(), "", curProject.getDbName(), curProject.getId());
                    task.getRsrc().add(tr);
                    task.setTaskUse("true");
                }
            }

            work.add(task);
            linkBatch.add(link);
        }

    }

    private void checkFFRsrc(ProjectNode task, String rsrShortName, Double plannedUnits) {
        for (SQLTaskRsrc tr : task.getRsrc()) {
            if (tr.getRsrcShortName().equals(rsrShortName)) {
                Double units = tr.getPlannedUnits();
                tr.setPlannedUnits(plannedUnits + units);
                tr.updateSQL();
                if (plannedUnits + units < 0.001) task.getRsrc().remove(tr);
                return;
            }
        }
    }

    //region checkFactor(int row) - проверка внесенного коэффициента, вызов из editingStopped()
    private void checkFactor(int row) {

        addButton.setEnabled(true);
        addButton.setIcon(null);
        addButton.setText("Добавить");
        arrCheck.clear();

        int smrId = tableModel.getSmRowId(row);
        BigDecimal summ = new BigDecimal(0);

        for (SQLLink link : tableModel.getData()) {
            if (link.getSmrId() != smrId) continue;
            if (link.getAction().equals("Создать")) {
                summ = summ.add(link.getFact());
            } else {
                for (SQLLink oldLink : linkArray.getLinkArray()) {
                    if (oldLink.getTaskId() == link.getTaskId() && oldLink.getSmrId() == link.getSmrId()) {
                        summ = summ.subtract(oldLink.getFact()).add(link.getFact());
                    }
                }
            }
            if (link.getFact().signum() == -1)
                arrCheck.add(linkViewTable.getValueAt(row, 4));
        }

        for (SmetNode currSmr : smet) {
            if (currSmr.getId() != smrId) continue;
            summ = summ.add(currSmr.getFactor());
        }

        if (summ.compareTo(new BigDecimal(linkViewTable.getValueAt(row, 9).toString())) == 1) {
            arrCheck.add(linkViewTable.getValueAt(row, 4));

            addButton.setEnabled(false);
            addButton.setText("");
            addButton.setIcon(new ImageIcon(getClass().getResource("sad.png")));
        }

        linkViewTable.validate();
    }
    //endregion

}

class ColorTableCellRenderer extends DefaultTableCellRenderer {

    private ArrayList arrCheck;
    private HashMap<String, Color> colorRow;

    public ColorTableCellRenderer(ArrayList arrCheck, HashMap<String, Color> colorRow) {
        this.colorRow = colorRow;
        this.arrCheck = arrCheck;
    }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        super.setBorder(new EmptyBorder(new Insets(1,3,1,3)));
        if (column == 8 || column == 9) {
            super.setBackground(isSelected ? Color.LIGHT_GRAY : new Color(227, 227, 227));
        } else {
            super.setBackground(isSelected ? new Color(227, 227, 227) : colorRow.get(table.getValueAt(row, 4)));
        }

        super.setForeground(isSelected ? Color.black : Color.black);
        super.setText(value != null ? value.toString() : "");
        super.setFont(new Font(null, Font.PLAIN, 11));
        if (column == 7) {
            super.setFont(new Font(null, Font.BOLD, 11));
        }

        for (Object anArrCheck : arrCheck) {
            if (table.getValueAt(row, 4) == anArrCheck) {
                super.setBackground(isSelected ? new Color(234, 124, 124) : new Color(234, 65, 49));
            }
        }

        return this;
    }
}

class ColorCheckBoxRenderer extends DefaultTableCellRenderer {

    private JCheckBox box = new JCheckBox();
    private ArrayList arrCheck;
    private HashMap<String, Color> colorRow;

    public ColorCheckBoxRenderer(ArrayList arrCheck, HashMap<String, Color> colorRow) {
        super();
        this.colorRow = colorRow;
        this.arrCheck = arrCheck;
    }

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
        box.setBackground(isSelected ? new Color(227, 227, 227) : colorRow.get(table.getValueAt(row, 4)));
        box.setForeground(isSelected ? Color.black : Color.black);
        box.setSelected((Boolean) value);
        for (Object anArrCheck : arrCheck) {
            if (table.getValueAt(row, 4) == anArrCheck) {
                box.setBackground(isSelected ? new Color(234, 124, 124) : new Color(234, 65, 49));
            }
        }

        return box;
    }

}

class CellRenderer extends JTextArea implements TableCellRenderer {

    private ArrayList arrCheck;
    private HashMap<String, Color> colorRow;

    public CellRenderer(ArrayList arrCheck, HashMap<String, Color> colorRow) {
        super();
        this.colorRow = colorRow;
        this.arrCheck = arrCheck;
        setLineWrap(true);
        setWrapStyleWord(true);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object arg1, boolean isSelected, boolean hasFocus, int row, int column) {
        super.setBorder(new EmptyBorder(new Insets(3,3,3,3)));
        if (column == 8 || column == 9) {
            super.setBackground(isSelected ? Color.LIGHT_GRAY : new Color(227, 227, 227));
        } else {
            super.setBackground(isSelected ? new Color(227, 227, 227) : colorRow.get(table.getValueAt(row, 4)));
        }
        super.setForeground(isSelected ? Color.black : Color.black);
        String data = arg1.toString();
        int lineWidth = this.getFontMetrics(this.getFont()).stringWidth(data);
        int lineHeight = this.getFontMetrics(this.getFont()).getHeight();
        int rowWidth = table.getCellRect(row, column, true).width;

        int newRowHeight = ((lineWidth / rowWidth) * (lineHeight)) + lineHeight * 2;
//        if (table.getRowHeight(row) < newRowHeight) {
            table.setRowHeight(row, newRowHeight);
//        }
        this.setText(data);
        this.setFont(new Font("Calibri", 0, 12));
        for (Object anArrCheck : arrCheck) {
            if (table.getValueAt(row, 4) == anArrCheck) {
                super.setBackground(isSelected ? new Color(234, 124, 124) : new Color(234, 65, 49));
            }
        }
        return this;
    }
}
